home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_include / ASM-ALPH.{_4 / BITOPS.H < prev    next >
C/C++ Source or Header  |  1999-09-17  |  7KB  |  292 lines

  1. #ifndef _ALPHA_BITOPS_H
  2. #define _ALPHA_BITOPS_H
  3.  
  4. /*
  5.  * Copyright 1994, Linus Torvalds.
  6.  */
  7.  
  8. /*
  9.  * These have to be done with inline assembly: that way the bit-setting
  10.  * is guaranteed to be atomic. All bit operations return 0 if the bit
  11.  * was cleared before the operation and != 0 if it was not.
  12.  *
  13.  * To get proper branch prediction for the main line, we must branch
  14.  * forward to code at the end of this object's .text section, then
  15.  * branch back to restart the operation.
  16.  *
  17.  * bit 0 is the LSB of addr; bit 64 is the LSB of (addr+1).
  18.  */
  19.  
  20. extern __inline__ void set_bit(unsigned long nr, volatile void * addr)
  21. {
  22.     unsigned long oldbit;
  23.     unsigned long temp;
  24.     unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
  25.  
  26.     __asm__ __volatile__(
  27.     "1:    ldl_l %0,%1\n"
  28.     "    and %0,%3,%2\n"
  29.     "    bne %2,2f\n"
  30.     "    xor %0,%3,%0\n"
  31.     "    stl_c %0,%1\n"
  32.     "    beq %0,3f\n"
  33.     "2:\n"
  34.     ".section .text2,\"ax\"\n"
  35.     "3:    br 1b\n"
  36.     ".previous"
  37.     :"=&r" (temp), "=m" (*m), "=&r" (oldbit)
  38.     :"Ir" (1UL << (nr & 31)), "m" (*m));
  39. }
  40.  
  41. extern __inline__ void clear_bit(unsigned long nr, volatile void * addr)
  42. {
  43.     unsigned long oldbit;
  44.     unsigned long temp;
  45.     unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
  46.  
  47.     __asm__ __volatile__(
  48.     "1:    ldl_l %0,%1\n"
  49.     "    and %0,%3,%2\n"
  50.     "    beq %2,2f\n"
  51.     "    xor %0,%3,%0\n"
  52.     "    stl_c %0,%1\n"
  53.     "    beq %0,3f\n"
  54.     "2:\n"
  55.     ".section .text2,\"ax\"\n"
  56.     "3:    br 1b\n"
  57.     ".previous"
  58.     :"=&r" (temp), "=m" (*m), "=&r" (oldbit)
  59.     :"Ir" (1UL << (nr & 31)), "m" (*m));
  60. }
  61.  
  62. extern __inline__ void change_bit(unsigned long nr, volatile void * addr)
  63. {
  64.     unsigned long temp;
  65.     unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
  66.  
  67.     __asm__ __volatile__(
  68.     "1:    ldl_l %0,%1\n"
  69.     "    xor %0,%2,%0\n"
  70.     "    stl_c %0,%1\n"
  71.     "    beq %0,3f\n"
  72.     ".section .text2,\"ax\"\n"
  73.     "3:    br 1b\n"
  74.     ".previous"
  75.     :"=&r" (temp), "=m" (*m)
  76.     :"Ir" (1UL << (nr & 31)), "m" (*m));
  77. }
  78.  
  79. extern __inline__ unsigned long test_and_set_bit(unsigned long nr,
  80.                          volatile void * addr)
  81. {
  82.     unsigned long oldbit;
  83.     unsigned long temp;
  84.     unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
  85.  
  86.     __asm__ __volatile__(
  87.     "1:    ldl_l %0,%1\n"
  88.     "    and %0,%3,%2\n"
  89.     "    bne %2,2f\n"
  90.     "    xor %0,%3,%0\n"
  91.     "    stl_c %0,%1\n"
  92.     "    beq %0,3f\n"
  93.     "2:\n"
  94.     ".section .text2,\"ax\"\n"
  95.     "3:    br 1b\n"
  96.     ".previous"
  97.     :"=&r" (temp), "=m" (*m), "=&r" (oldbit)
  98.     :"Ir" (1UL << (nr & 31)), "m" (*m));
  99.  
  100.     return oldbit != 0;
  101. }
  102.  
  103. extern __inline__ unsigned long test_and_clear_bit(unsigned long nr,
  104.                            volatile void * addr)
  105. {
  106.     unsigned long oldbit;
  107.     unsigned long temp;
  108.     unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
  109.  
  110.     __asm__ __volatile__(
  111.     "1:    ldl_l %0,%1\n"
  112.     "    and %0,%3,%2\n"
  113.     "    beq %2,2f\n"
  114.     "    xor %0,%3,%0\n"
  115.     "    stl_c %0,%1\n"
  116.     "    beq %0,3f\n"
  117.     "2:\n"
  118.     ".section .text2,\"ax\"\n"
  119.     "3:    br 1b\n"
  120.     ".previous"
  121.     :"=&r" (temp), "=m" (*m), "=&r" (oldbit)
  122.     :"Ir" (1UL << (nr & 31)), "m" (*m));
  123.  
  124.     return oldbit != 0;
  125. }
  126.  
  127. extern __inline__ unsigned long test_and_change_bit(unsigned long nr,
  128.                             volatile void * addr)
  129. {
  130.     unsigned long oldbit;
  131.     unsigned long temp;
  132.     unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
  133.  
  134.     __asm__ __volatile__(
  135.     "1:    ldl_l %0,%1\n"
  136.     "    and %0,%3,%2\n"
  137.     "    xor %0,%3,%0\n"
  138.     "    stl_c %0,%1\n"
  139.     "    beq %0,3f\n"
  140.     ".section .text2,\"ax\"\n"
  141.     "3:    br 1b\n"
  142.     ".previous"
  143.     :"=&r" (temp), "=m" (*m), "=&r" (oldbit)
  144.     :"Ir" (1UL << (nr & 31)), "m" (*m));
  145.  
  146.     return oldbit != 0;
  147. }
  148.  
  149. extern __inline__ unsigned long test_bit(int nr, volatile void * addr)
  150. {
  151.     return 1UL & (((const int *) addr)[nr >> 5] >> (nr & 31));
  152. }
  153.  
  154. /*
  155.  * ffz = Find First Zero in word. Undefined if no zero exists,
  156.  * so code should check against ~0UL first..
  157.  *
  158.  * Do a binary search on the bits.  Due to the nature of large
  159.  * constants on the alpha, it is worthwhile to split the search.
  160.  */
  161. extern inline unsigned long ffz_b(unsigned long x)
  162. {
  163.     unsigned long sum = 0;
  164.  
  165.     x = ~x & -~x;        /* set first 0 bit, clear others */
  166.     if (x & 0xF0) sum += 4;
  167.     if (x & 0xCC) sum += 2;
  168.     if (x & 0xAA) sum += 1;
  169.  
  170.     return sum;
  171. }
  172.  
  173. extern inline unsigned long ffz(unsigned long word)
  174. {
  175. #ifdef __alpha_cix__
  176.     /* Whee.  EV6 can calculate it directly.  */
  177.     unsigned long result;
  178.     __asm__("ctlz %1,%0" : "=r"(result) : "r"(~word));
  179.     return result;
  180. #else
  181.     unsigned long bits, qofs, bofs;
  182.  
  183.     __asm__("cmpbge %1,%2,%0" : "=r"(bits) : "r"(word), "r"(~0UL));
  184.     qofs = ffz_b(bits);
  185.     __asm__("extbl %1,%2,%0" : "=r"(bits) : "r"(word), "r"(qofs));
  186.     bofs = ffz_b(bits);
  187.  
  188.     return qofs*8 + bofs;
  189. #endif
  190. }
  191.  
  192. #ifdef __KERNEL__
  193.  
  194. /*
  195.  * ffs: find first bit set. This is defined the same way as
  196.  * the libc and compiler builtin ffs routines, therefore
  197.  * differs in spirit from the above ffz (man ffs).
  198.  */
  199.  
  200. extern inline int ffs(int word)
  201. {
  202.     int result = ffz(~word);
  203.     return word ? result+1 : 0;
  204. }
  205.  
  206. /*
  207.  * hweightN: returns the hamming weight (i.e. the number
  208.  * of bits set) of a N-bit word
  209.  */
  210.  
  211. #ifdef __alpha_cix__
  212. /* Whee.  EV6 can calculate it directly.  */
  213. extern __inline__ unsigned long hweight64(unsigned long w)
  214. {
  215.     unsigned long result;
  216.     __asm__("ctpop %1,%0" : "=r"(result) : "r"(w));
  217.     return result;
  218. }
  219.  
  220. #define hweight32(x) hweight64((x) & 0xfffffffful)
  221. #define hweight16(x) hweight64((x) & 0xfffful)
  222. #define hweight8(x)  hweight64((x) & 0xfful)
  223. #else
  224. #define hweight32(x) generic_hweight32(x)
  225. #define hweight16(x) generic_hweight16(x)
  226. #define hweight8(x)  generic_hweight8(x)
  227. #endif
  228.  
  229. #endif /* __KERNEL__ */
  230.  
  231. /*
  232.  * Find next zero bit in a bitmap reasonably efficiently..
  233.  */
  234. extern inline unsigned long find_next_zero_bit(void * addr, unsigned long size, unsigned long offset)
  235. {
  236.     unsigned long * p = ((unsigned long *) addr) + (offset >> 6);
  237.     unsigned long result = offset & ~63UL;
  238.     unsigned long tmp;
  239.  
  240.     if (offset >= size)
  241.         return size;
  242.     size -= result;
  243.     offset &= 63UL;
  244.     if (offset) {
  245.         tmp = *(p++);
  246.         tmp |= ~0UL >> (64-offset);
  247.         if (size < 64)
  248.             goto found_first;
  249.         if (~tmp)
  250.             goto found_middle;
  251.         size -= 64;
  252.         result += 64;
  253.     }
  254.     while (size & ~63UL) {
  255.         if (~(tmp = *(p++)))
  256.             goto found_middle;
  257.         result += 64;
  258.         size -= 64;
  259.     }
  260.     if (!size)
  261.         return result;
  262.     tmp = *p;
  263. found_first:
  264.     tmp |= ~0UL << size;
  265. found_middle:
  266.     return result + ffz(tmp);
  267. }
  268.  
  269. /*
  270.  * The optimizer actually does good code for this case..
  271.  */
  272. #define find_first_zero_bit(addr, size) \
  273.     find_next_zero_bit((addr), (size), 0)
  274.  
  275. #ifdef __KERNEL__
  276.  
  277. #define ext2_set_bit                 test_and_set_bit
  278. #define ext2_clear_bit               test_and_clear_bit
  279. #define ext2_test_bit                test_bit
  280. #define ext2_find_first_zero_bit     find_first_zero_bit
  281. #define ext2_find_next_zero_bit      find_next_zero_bit
  282.  
  283. /* Bitmap functions for the minix filesystem.  */
  284. #define minix_set_bit(nr,addr) test_and_set_bit(nr,addr)
  285. #define minix_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
  286. #define minix_test_bit(nr,addr) test_bit(nr,addr)
  287. #define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
  288.  
  289. #endif /* __KERNEL__ */
  290.  
  291. #endif /* _ALPHA_BITOPS_H */
  292.